#ifndef NETLIB_CHANNEL_H
#define NETLIB_CHANNEL_H

// 将描述符和事件绑定的通道类

#include "noncopyable.h"
#include "Timestamp.h"

#include <functional>
#include <memory>

namespace netlib
{

namespace net
{

class EventLoop;

class Channel : noncopyable // 将描述符和事件绑定的通道类 不可拷贝
{
public:
    typedef std::function<void()> EventCallback; // 事件回调处理
    typedef std::function<void(Timestamp)> ReadEventCallback; // 事件读取回调处理

    Channel(EventLoop* loop, int fd); // 确定所属的EventLoop对象，Channel只能在一个线程处理

    ~Channel();

    void handleEvent(Timestamp receiveTime); // 事件处理回调函数，handleEventWithGuard的封装

    void setReadCallback(ReadEventCallback cb) // 设置读取回调函数
    { readCallback_ = std::move(cb); }

    void setWriteCallback(EventCallback cb) // 设置写入回调函数
    { writeCallback_ = std::move(cb); }

    void setCloseCallback(EventCallback cb) // 设置关闭回调函数
    { closeCallback_ = std::move(cb); }

    void setErrorCallback(EventCallback cb) // 设置错误回调函数
    { errorCallback_ = std::move(cb); }

    void tie(const std::shared_ptr<void>&); // 保存TCP连接的副本指针并设置标识

    int fd() const { return fd_; } // 返回持有的描述符

    int events() const { return events_; } // 返回fd上注册的事件

    void set_revents(int revt) { revents_ = revt; } // 设置poll/epoll返回的事件

    // 判断事件是否为空    
    bool isNoneEvent() const { return events_ == kNoneEvent; }

    // 向poll/epoll注册可读事件
    void enableReading() { events_ |= kReadEvent; update(); }

    // 向poll/epoll撤销可读事件
    void disableReading() { events_ &= ~kReadEvent; update(); }

    // 向poll/epoll注册可写事件
    void enableWriting() { events_ |= kWriteEvent; update(); }

    // 向poll/epoll撤销可写事件
    void disableWriting() { events_ &= ~kWriteEvent; update(); }

    // 向poll/epoll撤销所有事件
    void disableAll() { events_ = kNoneEvent; update(); }

    // 判断当前通道注册的事件是否为可写
    bool isWriting() const { return events_ & kWriteEvent; }

    // 判断当前通道注册的事件是否为可读
    bool isReading() const { return events_ & kReadEvent; }

    // 获得事件在poll/epoll数组中的序号
    int index() { return index_; }

    // 设置事件在poll/epoll数组中的序号
    void set_index(int idx) { index_ = idx; }

    string reventsToString() const; // 作为调试用途，将发生的事件转化成string返回

    string eventsToString() const; // 作为调试用途，将注册的事件转化成string返回

    void doNotLogHup() { logHup_ = false; } // 设置日志中不记录HUP事件

    EventLoop* ownerLoop() { return loop_; } // 返回该对象所属的EventLoop对象指针

    void remove(); // 从事件表中移除该通道

private:
    static string eventsToString(int fd, int ev); // 将事件转换成string返回

    void update(); // 事件表更新

    void handleEventWithGuard(Timestamp receiveTime); // 事件处理回调函数

    static const int kNoneEvent;        // 事件状态：暂无事件
    static const int kReadEvent;        // 事件状态：可读或者紧急数据
    static const int kWriteEvent;       // 事件状态：可写

    EventLoop* loop_;       // 该对象所属的EventLoop
    const int  fd_;         // 事件描述符，不管理生命周期
    int        events_;     // 描述符注册的事件
    int        revents_;    // poll/epoll返回的事件
    int        index_;      // 标识在poll事件数组中的序号，epoll中代表事件表的事件状态
    bool       logHup_;     // 日志中是否记录HUP事件，默认开启

    std::weak_ptr<void> tie_;           // 弱引用智能指针，引用计数不会加一
                                        // 连接成功后，每次处理通道都提升保证连接不析构
                                        // 和tied_一起用来安全的断开连接

    bool tied_;                         // 标志保存连接的weak_ptr副本
    bool eventHandling_;                // 是否正在处理事件
    bool addedToLoop_;                  // 标识该通道是否在事件表中
    ReadEventCallback readCallback_;    // 可读事件回调函数
    EventCallback writeCallback_;       // 可写事件回调函数
    EventCallback closeCallback_;       // 关闭事件回调函数
    EventCallback errorCallback_;       // 错误事件回调函数

}; // class Channel end

} // namespace net end

} // namespace netlib end

#endif